// src/utils/request.ts
import axios, { type AxiosInstance, type AxiosRequestConfig } from 'axios'
import { ElMessage, ElMessageBox } from 'element-plus'
import { useLoadingStore, useAuthStore } from '@/store'

// 定义响应数据格式
interface ResponseData<T = any> {
    code: number
    data: T
    message: string
}

// 扩展 axios 配置
interface RequestConfig extends AxiosRequestConfig {
    showLoading?: boolean
    needToken?: boolean
}

class Request {
    private instance: AxiosInstance
    private loadingStore = useLoadingStore()
    private authStore = useAuthStore()

    constructor() {
        this.instance = axios.create({
            baseURL: import.meta.env.VITE_APP_BASE_API,
            timeout: 10000,
            withCredentials: true,
            paramsSerializer: params => {
                return new URLSearchParams(params).toString()
            }
        })

        this.initInterceptors()
    }

    // 初始化拦截器
    private initInterceptors() {
        // 请求拦截
        this.instance.interceptors.request.use(
            config => {
                // 加载状态
                if (config.showLoading) {
                    this.loadingStore.addLoading()
                }

                // Token 处理
                if (config.needToken !== false && this.authStore.token) {
                    config.headers!['Authorization'] = `Bearer ${this.authStore.token}`
                }

                // 请求取消
                const controller = new AbortController()
                config.signal = controller.signal
                this.loadingStore.addController(controller)

                return config
            },
            error => {
                this.loadingStore.subLoading()
                return Promise.reject(error)
            }
        )

        // 响应拦截
        this.instance.interceptors.response.use(
            response => {
                this.loadingStore.subLoading()
                const res = response.data

                if (res.code !== 200) {
                    this.handleError(res.code, res.message)
                    return Promise.reject(new Error(res.message || 'Error'))
                }
                return res.data
            },
            error => {
                this.loadingStore.subLoading()
                this.handleHttpError(error)
                return Promise.reject(error)
            }
        )
    }

    // 错误处理
    private handleError(code: number, message: string) {
        const errorMap: Record<number, () => void> = {
            401: () => {
                ElMessageBox.confirm('登录已过期，请重新登录', '提示', {
                    confirmButtonText: '重新登录',
                    cancelButtonText: '取消',
                    type: 'warning'
                }).then(() => {
                    this.authStore.logout()
                    window.location.href = '/login'
                })
            },
            403: () => {
                ElMessage.error('没有操作权限')
            },
            500: () => {
                ElMessage.error('服务器错误')
            }
        }

        errorMap[code]?.() || ElMessage.error(message || '未知错误')
    }

    // HTTP 错误处理
    private handleHttpError(error: any) {
        if (error.code === 'ECONNABORTED') {
            ElMessage.error('请求超时')
            return
        }

        if (error.response) {
            const status = error.response.status
            this.handleError(status, error.response.data?.message)
        } else {
            ElMessage.error('网络连接异常')
        }
    }

    // 封装请求方法
    public request<T = any>(config: RequestConfig): Promise<T> {
        return this.instance.request(config)
    }

    public get<T = any>(url: string, config?: RequestConfig): Promise<T> {
        return this.request({ ...config, url, method: 'GET' })
    }

    public post<T = any>(url: string, data?: any, config?: RequestConfig): Promise<T> {
        return this.request({ ...config, url, data, method: 'POST' })
    }
    // ....
}

export default new Request()